﻿using System.Text;
using MultiAgentsClient.Shared;
using OpenAI.ObjectModels;

namespace MultiAgentsServer.Scripts.Shared;

public class PromptMessagesConsts
{
    public static List<LlmMessageSimp> ReplyAssistantOptions(string chatHistory)
    {
        return [
            new (StaticValues.ChatMessageRoles.System,
            "### 你的任务\r\n" +
            "你被提供了一个包含用户和LLM（大语言模型） 对话的聊天记录作为上下文， 其中有三类消息：user: 用户信息， LLM： 大语言模型的回复， 以及ToolCall： 大语言模型进行toolCall所返回的结果。 对话记录的最后条一定是LLM的回复。 \r\n" +
            "你的任务是预测user接下来要对LLM说或者问什么。\r\n" +
            "提供 2~6 个预测。每个应该是一个短语。\r\n" +
            "非常重要的是，它们之间用分号（;）分隔。\r\n" +
            "你不应该回复其他任何内容，不要解释。\r\n" +
            "\r\n" +
            "### 假如聊天记录的最新的几条消息和toolcall有关\r\n" +
            "1. LLM通常会询问下一步需要做什么或者想要执行下一步toolcall以分析问题， 那么你需要基于上下文以及LLM给出的提示去预测user要说的话\r\n" +
            "2. 假如LLM直言想要执行某个toolcall， 那么也请提供类似于 '好的' 这类的预测\r\n" +
            "\r\n" +
            "### 假如聊天记录是关于知识点的询问， 那么遵从以下提问的原则\r\n" +
            "1. 树状结构的提问法：从一般到具体、分层次级别的学习方法。首先了解最高层次的概念来形成广泛的知识框架，然后逐渐探索较低层次的细节。\r\n" +
            "2. 理解技术词汇：在学习新概念时，不理解的技术术语会妨碍你的整体理解。确保你正确理解这些技术术语，以准确掌握整个概念。"),
            new (StaticValues.ChatMessageRoles.User, chatHistory)
            ];
    }

    public static List<LlmMessageSimp> RoomRenamingMessages(string chatHistory)
    {
        return [
            new (StaticValues.ChatMessageRoles.System,
            "I create a chatroom with the following message from user and gpt, your role is to give me a summary of the chat history in a very short name. " +
            "Only reply the chatroom name, nothing else. "),
            new (StaticValues.ChatMessageRoles.User, chatHistory)
            ];
    }

    public static List<LlmMessageSimp> WorkflowSwitchNodeMessages(string chatHistory, string inputMessage, List<string> categories)
    {
        StringBuilder categoriesJson = new();
        categoriesJson.Append('[');

        for (int i = 0; i < categories.Count; i++)
        {
            string category = categories[i];
            categoriesJson.Append($"{{\"category_id\": \"{i}\",\"category_name\": \"{category}\"}}");
            if (i < categories.Count - 1)
            {
                categoriesJson.Append(", ");
            }
        }

        categoriesJson.Append(']');
        return [
            new (StaticValues.ChatMessageRoles.System,
            "\n    " +
            "### Job Description',\n    " +
            "You are a text classification engine that analyzes text data and assigns categories based on user input or automatically determined categories.\n    " +
            "### Task\n    " +
            "Your task is to assign one categories ONLY to the input text and only one category may be assigned returned in the output.Additionally, you need to extract the key words from the text that are related to the classification.\n    " +
            "### Format\n    " +
            "The input text is in the variable text_field.Categories are specified as a category list with two filed category_id and category_name in the variable categories .Classification instructions may be included to improve the classification accuracy.\n    " +
            "### Constraint\n    " +
            "DO NOT include anything other than the JSON array in your response.\n    " +
            "### Memory\n    " +
            "Here is the chat histories between human and assistant, inside <histories></histories> XML tags.\n    " +
            "<histories>\n    " +
            "\n    " + chatHistory +
            "</histories>\n" +
            ""),
            new (StaticValues.ChatMessageRoles.User,
            "\n    " +
            "{ \"input_text\": [\"I recently had a great experience with your company. The service was prompt and the staff was very friendly.\"],\n    " +
            "\"categories\": [{\"category_id\":\"0\",\"category_name\":\"Customer Service\"},{\"category_id\":\"1\",\"category_name\":\"Satisfaction\"},{\"category_id\":\"2\",\"category_name\":\"Sales\"},{\"category_id\":\"3\",\"category_name\":\"Product\"}],\n    " +
            "\"classification_instructions\": [\"classify the text based on the feedback provided by customer\"]}\n"),
            new (StaticValues.ChatMessageRoles.Assistant,
            "\n" +
            "{\"keywords\": [\"recently\", \"great experience\", \"company\", \"service\", \"prompt\", \"staff\", \"friendly\"],\n    " +
            "\"category_id\":\"0\",\n" +
            "\"category_name\": \"Customer Service\"}\n" +
            "\n"),
            new (StaticValues.ChatMessageRoles.User,
            "\n    " +
            "{\"input_text\": [\"bad service, slow to bring the food\"],\n    " +
            "\"categories\": [{\"category_id\":\"0\",\"category_name\":\"Food Quality\"},{\"category_id\":\"1\",\"category_name\":\"Experience\"},{\"category_id\":\"2\",\"category_name\":\"Price\"}],\n    " +
            "\"classification_instructions\": []}\n"),
            new (StaticValues.ChatMessageRoles.Assistant,
            "{\"keywords\": [\"bad service\", \"slow\", \"food\", \"tip\", \"terrible\", \"waitresses\"],\n    " +
            "\"category_id\":\"1\",\n" +
            "\"category_name\": \"Experience\"}\n" +
            "\n"),
            new LlmMessageSimp(StaticValues.ChatMessageRoles.User,
            "\n    '{\"input_text\": [\"" + inputMessage +
            "\"],',\n    '\"categories\": [" + categoriesJson + "], ',\n    '\"classification_instructions\": [\"\"]}'\n"
            )];
    }

    public static List<LlmMessageSimp> WorkflowParameterExtractionMessages(string chatHistory, string context, string description)
    {
        return [
            new (StaticValues.ChatMessageRoles.System,
            "\n    " +
            "### Job Description',\n    " +
            "You are a helpful assistant tasked with extracting structured information based on specific criteria provided. Follow the guidelines below to ensure consistency and accuracy.\n    " +
            "### Task\n    " +
            "Ensure that the information extraction is contextual and aligns with the provided criteria.\n    " +
            "### Instructions:\n    " +
            "Some additional information is provided below. Always adhere to these instructions as closely as possible:\\n<instruction>\\n\\n</instruction>\\nSteps:\\n\r\n" +
            "1. Review the chat history provided within the <histories> tags.\\n\r\n" +
            "2. Extract the relevant information based on the criteria given, output multiple values if there is multiple relevant information that match the criteria in the given text. \\n\r\n" +
            "3. Generate a well-formatted output using the defined functions and arguments.\\n\r\n" +
            "4. Do not include any XML tags in your output.\\n" +
            "### Final Output\n" +
            "Produce well-formatted function calls in string without XML tags, as shown in the example.\n" +
            "### Memory\n    " +
            "Here is the chat histories between human and assistant, inside <histories></histories> XML tags.\n    " +
            "<histories>\n    " +
            "\n    " + chatHistory +
            "</histories>\n" +
            ""),
            new (StaticValues.ChatMessageRoles.User,
            "### Structure\nHere is the structure of the JSON object, you should always follow the structure.\n<structure>\n" +
            "{\"type\": \"object\", \"properties\": {\"location\": {\"type\": \"string\", \"description\": \"The location to get the weather information\", \"required\": true}}, \"required\": [\"location\"]}\n</structure>\n\n" +
            "### Text to be converted to JSON\nInside <text></text> XML tags, there is a text that you should convert to a JSON object.\n" +
            "<text>\nWhat is the weather today in SF?\n</text>\n"),
            new (StaticValues.ChatMessageRoles.Assistant,
            "San Francisco"),
            new (StaticValues.ChatMessageRoles.User,
            "### Structure\nHere is the structure of the JSON object, you should always follow the structure.\n" +
            "<structure>\n{\"type\": \"object\", \"properties\": {\"food\": {\"type\": \"string\", \"description\": \"The food to eat\", \"required\": true}}, \"required\": [\"food\"]}\n</structure>\n\n" +
            "### Text to be converted to JSON\nInside <text></text> XML tags, there is a text that you should convert to a JSON object.\n" +
            "<text>\nI want to eat some apple pie.\n</text>\n"),
            new (StaticValues.ChatMessageRoles.Assistant,
            "apple pie"),
            new LlmMessageSimp(StaticValues.ChatMessageRoles.User,
            "### Structure\nHere is the structure of the JSON object, you should always follow the structure.\n" +
            "<structure>\n{\"type\": \"object\", \"properties\": {\"v\": {\"description\": \"" + description + "\", \"type\": \"string\"}}, \"required\": []}\n</structure>\n\n" +
            "### Text to be converted to JSON\nInside <text></text> XML tags, there is a text that you should convert to a JSON object.\n" +
            "<text>\n" + context + "\n</text>\n"
            )];
    }
}

public class NameConsts
{
    public static string DefaultModelName { get; } = "DefaultModel";
    public static string DefaultUserName { get; } = "DefaultUserName";
    public static string DefaultProjectName { get; } = "DefaultProjectName";
    public static string DefaultChatRoomName { get; } = "DefaultChatRoomName";
    public static string NewAgentName { get; } = "NewAgent";
    public static string DefaultAgentName { get; } = "DefaultAgent";
    public static string GitOperatorAgentName { get; } = "Git操作助手";
    public static string OctoHelperAgentName { get; } = "Octo配置助手";
}

public class ModelConsts
{
    public enum LlmModels
    {
        Gpt_4o_mini = 0,
        Gpt_4o = 1,
        Gpt_4_turbo_2024_04_09 = 2,
        Llama3_70b = 3,
        Qwen2_72b = 4,
        Qwen2_72b_instruct = 5,
    }

    public class ModelInfo
    {
        public string ModelName = "";
        public int ContextWindow;
    }

    //Used for request
    public static List<string> ModelNames =>
        modelInfos.OrderBy(m => m.Key).Select(m => m.Value.ModelName).ToList();

    public static readonly Dictionary<LlmModels, ModelInfo> modelInfos = new()
    {
        {
            LlmModels.Gpt_4o_mini,
            new ModelInfo
            {
                ModelName = Models.EnumToString(Models.Model.Gpt_4o_mini_2024_07_18),
                ContextWindow = 128000
            }
        },
        {
            LlmModels.Gpt_4o,
            new ModelInfo
            {
                ModelName = Models.EnumToString(Models.Model.Gpt_4o_2024_05_13),
                ContextWindow = 128000
            }
        },
        {
            LlmModels.Gpt_4_turbo_2024_04_09,
            new ModelInfo
            {
                ModelName = Models.EnumToString(Models.Model.Gpt_4_turbo_2024_04_09),
                ContextWindow = 128000
            }
        },
        {
            LlmModels.Llama3_70b,
            new ModelInfo
            {
                ModelName = LlmModels.Llama3_70b.ToString(),
                ContextWindow = 8200
            }
        },
        {
            LlmModels.Qwen2_72b,
            new ModelInfo
            {
                ModelName = LlmModels.Qwen2_72b.ToString(),
                ContextWindow = 128000
            }
        },
        {
            LlmModels.Qwen2_72b_instruct,
            new ModelInfo
            {
                ModelName = LlmModels.Qwen2_72b_instruct.ToString(),
                ContextWindow = 128000
            }
        },

    };
}

public class MessageConsts
{
    public static readonly string InitRespondMessage = "Init message.";
    public static readonly string NoneRespoenseMessage = "No message responsed from openai api.";
}

public class FileConsts
{
#if BACKEND
#if LOCALDEV
    public static string LogFileName { get; } = @"MultiAgents\log_server_localdev.txt";
#elif DEVELOP
    public static string LogFileName { get; } = @"MultiAgents\log_server_develop.txt";
#else //Release
    public static string LogFileName { get; } = @"MultiAgents\log_server_release.txt";
#endif
#elif FRONTEND
#if LOCALDEV
    public static string LogFileName { get; } = @"MultiAgents\log_client_localdev.txt";
#elif DEVELOP
    public static string LogFileName { get; } = @"MultiAgents\log_client_develop.txt";
#else //Release
    public static string LogFileName { get; } = @"MultiAgents\log_client_release.txt";
#endif
#endif

    public static string UpdateTemplateDirectoryName { get; } = @"MultiAgents\update";
    public static string VersionNumberFileName { get; } = @".\version.txt";
    public static string WorkflowPageFileName { get; } = @".\reactbuild\index.html";
    public static string MessagePageFileName { get; } = @".\Presentation\message_webview\Message.html";
}
